namespace SimpleWebServices.Web.UI.Html
{
    using System;
    using System.Xml;
    using System.Xml.Serialization;
    using SimpleWebServices;
    using SimpleWebServices.Globalization;
    using Xunit;

    public sealed class ElementFacts
    {
        [Fact]
        public void typedef()
        {
            Assert.True(new ObjectExpectations<Element>()
                .DerivesFrom<object>()
                .IsAbstractBaseClass()
                .Implements<IElement>()
                .XmlRoot("element")
                .Result);
        }

        [Fact]
        public void deserialize()
        {
            Element expected = new ElementDerived
            {
                Id = "id",
                Class = "class",
                Language = "fr",
                OnClick = "javascript:window.print()",
                Title = "title"
            };

            string xml = "<element id='id' class='class' lang='fr' title='title' onclick='javascript:window.print()' />";
            Element actual = xml.Deserialize<ElementDerived>();

            Assert.Equal<string>(expected.ToString(), actual.ToString());
        }

        [Fact]
        public void serialize()
        {
            Element obj = new ElementDerived
            {
                Id = "id",
                Class = "class",
                Language = "fr",
                OnClick = "javascript:window.print()",
                Title = "title"
            };

            string xpath = "1=count(/element[@id='id'][@class='class'][@lang='fr'][@title='title'][@onclick='javascript:window.print()'])";

            Assert.True((bool)obj.Serialize().CreateNavigator().Evaluate(xpath));
        }

        [Fact]
        public void ctor()
        {
            Assert.NotNull(new ElementDerived() as Element);
        }

        [Fact]
        public void prop_Class()
        {
            Assert.True(new PropertyExpectations(typeof(ElementDerived).GetProperty("Class"))
                .IsAutoProperty<Names>()
                .Result);
        }

        [Fact]
        public void prop_Id()
        {
            Assert.True(new PropertyExpectations(typeof(ElementDerived).GetProperty("Id"))
                .DefaultValueIsNull()
                .Set(new Name("token"))
                .Result);
        }

        [Fact]
        public void prop_Language()
        {
            Assert.True(new PropertyExpectations(typeof(ElementDerived).GetProperty("Language"))
                .IsAutoProperty<Language>()
                .Result);
        }

        [Fact]
        public void prop_OnClick()
        {
            Assert.True(new PropertyExpectations(typeof(ElementDerived).GetProperty("OnClick"))
                .IsAutoProperty<string>()
                .Result);
        }

        [Fact]
        public void prop_Title()
        {
            Assert.True(new PropertyExpectations(typeof(ElementDerived).GetProperty("Title"))
                .IsAutoProperty<string>()
                .Result);
        }

        [Fact]
        public void op_ToElement()
        {
            IElement expected = new ElementDerived();
            IElement actual = (expected as IElementSerializable).ToElement();

            Assert.Same(expected, actual);
        }

        [Fact]
        public void op_Deserialize_string_string_string()
        {
            IElementSerializable obj = (new ElementDerived() as IElementSerializable).Deserialize("text", null, "<text>value</text>");

            Assert.Null(obj);
        }

        [Fact]
        public void op_Render()
        {
            Element obj = new ElementDerived
            {
                Id = "id",
                Class = "class",
                Language = "fr",
                OnClick = "javascript:window.print()"
            };

            string xpath = "1=count(/element[@id='id'][@class='class'][@lang='fr'][@onclick='javascript:window.print()'])";

            Assert.True((bool)obj.Serialize().CreateNavigator().Evaluate(xpath));
        }

        [Fact]
        public void op_GetHashCode()
        {
            ElementDerived obj = new ElementDerived
            {
                Id = "id",
                Class = "class",
                Language = "fr"
            };

            int expected = obj.ToString().GetHashCode();
            int actual = obj.GetHashCode();

            Assert.Equal<int>(expected, actual);
        }

        [Fact]
        public void op_ToString()
        {
            Element obj = new ElementDerived
            {
                Id = "id",
                Class = "class",
                Language = "fr",
                OnClick = "javascript:window.print()",
                Title = "title"
            };

            string expected = obj.Render();
            string actual = obj.ToString();

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void op_ToStringDefault()
        {
            string expected = "<element />";
            string actual = new ElementDerived().ToString();

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void IXmlSerializable_op_GetSchema()
        {
            Assert.Throws<NotSupportedException>(() => (new ElementDerived() as IXmlSerializable).GetSchema());
        }

        [Fact]
        public void IXmlSerializable_op_ReadXml_XmlReaderNull()
        {
            Assert.Throws<ArgumentNullException>(() => (new ElementDerived() as IXmlSerializable).ReadXml(null as XmlReader));
        }

        [Fact]
        public void IXmlSerializable_op_WriteXml_XmlWriterNull()
        {
            Assert.Throws<ArgumentNullException>(() => (new ElementDerived() as IXmlSerializable).WriteXml(null as XmlWriter));
        }
    }
}